//Copyright 2012-2021 Keysight Technologies // //Licensed under the Apache License, Version 2.0 (the "License"); //you may not use this file except in compliance with the License. //You may obtain a copy of the License at // //http://www.apache.org/licenses/LICENSE-2.0 // //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. using System.ComponentModel; using System.Linq; namespace OpenTap.PluginDevelopment.Advanced_Examples { // Icon annotations can be used to provide custom context menu / right-click functionality // in settings user interfaces. This can for example be used to clear the value of a property. // let's try this. // to do this, we need a IMenuModel, a IMenuModelFactory and some custom Icon names. /// /// This menu model factory takes an IMemberData and decides if it can generate a model for it. /// public class MenuModelExampleFactory : IMenuModelFactory { public IMenuModel CreateModel(IMemberData member) { // our MenuModelExample works for all members that defines DefaultValueAttribute. if (member.HasAttribute()) { return new MenuModelExample(member); } return null; } } /// /// Shows how to add a menu model. This specific example is about DefaultValueAttribute. /// After compiling, try creating a DefaultValueExample test step and right-click it's setting. /// public class MenuModelExample : IMenuModel { readonly IMemberData member; /// This class requires the member to be specified. public MenuModelExample(IMemberData member) { this.member = member; } /// When multi-selecting, this holds more than one value. Otherwise, it just contains one step. public object[] Source { get; set; } // some code to check that the test step is in a state that is allowed to be modified. static bool testStepLocked(ITestStep step) { if (step.IsReadOnly) return true; if (step.Parent is ITestStep step2) return testStepLocked(step2); if (step.Parent is TestPlan plan) return plan.IsRunning || plan.Locked; return true; } public bool CanExecuteRevert => member.Writable && !Source.OfType().Any(testStepLocked); public bool IsAlreadyDefaultValues => Source.All(source => Equals(member.GetValue(source), member.GetAttribute()?.Value)); [Display("Revert to default", "Revert the value to it's default.")] // The is IconAnnotation is not generally important, it can be used by // user interfaces to identify which icon to associate with the action, if applicable. [IconAnnotation("MenuModelExample.RevertToDefault")] // This is needed because we are using Method annotations (not by default browsable). [Browsable(true)] // show it as grayed if not writable. [EnabledIf(nameof(CanExecuteRevert))] // show as grayed if the current value is the same as the default [EnabledIf(nameof(IsAlreadyDefaultValues), false)] public void RevertToDefault() // multiple methods can be added, each corresponding to another menu item. { // get the default value and set the property value(s). // try multi selecting to understand why we do a 'for-each'. var defaultValue = member.GetAttribute().Value; foreach (var source in Source) { member.SetValue(source, defaultValue); } } } }